/*
 * PuyoWindow.java
 *
 * Created on August 2, 2004 , PM 10:27
 */

/**
 * Puyo's Main Window, manage user interfaces such as keystroke events, image rendering
 * @author  Ming
 */

/**package name of Puyo game*/
package Puyo;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;


public class PuyoWindow implements KeyListener, Runnable {
  /**Main game window*/
  JFrame mainFrame;
  
  /**canvas for puyo balls, all renderings happen here*/
  //JPanel paintCanvas;
  Canvas paintCanvas;
  
  /**label for game score*/
  JLabel labelScore;
  
  /**contains game data and game logic*/
  PuyoLogic puyoLogic = null;

  /** 4 Puyo images, They are red, green, yellow, blue*/
  public Image puyoImages[];
  
  /*remove flickering*/
  private Image doubleBuffer;

  /**puyo board width */
  public static final int boardWidth=6;  
  /**puyo board height*/
  public static final int boardHeight=12;
  
  /** puyo balls size: width*/
  public static final int ballWidth = 32;
  /** puyo balls size: height*/
  public static final int ballHeight = 32;
  
  /** puyo canvas size: width*/
  public static final int canvasWidth = ballWidth*boardWidth;
  /** puyo camvas size: height*/
  public static final int canvasHeight = ballHeight*boardHeight;

  /**Load puyo images, init GUIs*/
  public PuyoWindow() {
    Toolkit toolkit = Toolkit.getDefaultToolkit();
  
    puyoImages = new Image[4];
    puyoImages[0] = toolkit.getImage(this.getClass().getResource("images/puyo_red.png"));
    puyoImages[1] = toolkit.getImage(this.getClass().getResource("images/puyo_green.png"));
    puyoImages[2] = toolkit.getImage(this.getClass().getResource("images/puyo_blue.png"));
    puyoImages[3] = toolkit.getImage(this.getClass().getResource("images/puyo_yellow.png"));
    
    mainFrame = new JFrame("PuyoWindow");

    Container cp = mainFrame.getContentPane();
  
    labelScore = new JLabel("Score:");
    cp.add(labelScore, BorderLayout.NORTH);
    
    paintCanvas = new Canvas();
    paintCanvas.addKeyListener(this);
    paintCanvas.setSize(canvasWidth,canvasHeight);
    //paintCanvas.setPreferredSize(new Dimension(canvasWidth,canvasHeight));
    //paintCanvas.setOpaque(true);
   
    cp.add(paintCanvas, BorderLayout.CENTER);
    
    JPanel panelButtom = new JPanel();
    panelButtom.setLayout(new BorderLayout());
    JLabel labelHelp;
    labelHelp = new JLabel("Start: S; Pause: P/SPACE", JLabel.CENTER);
    panelButtom.add(labelHelp, BorderLayout.NORTH);
    labelHelp = new JLabel("Speed: PgUp, PgDn", JLabel.CENTER);
    panelButtom.add(labelHelp, BorderLayout.CENTER);
    labelHelp = new JLabel("Move/Rotate: Arrow keys",JLabel.CENTER);
    panelButtom.add(labelHelp, BorderLayout.SOUTH);
    cp.add(panelButtom,BorderLayout.SOUTH);

    mainFrame.addKeyListener(this);
    mainFrame.pack();
    mainFrame.setResizable(false);
    mainFrame.setTitle("Puyo");
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.setVisible(true);
    beginPuyo();
  }

  /**process user key input, primary way to interact with the game*/
  public void keyPressed(KeyEvent e){
    int keyCode = e.getKeyCode();
    if (puyoLogic.isRunning())
      switch(keyCode){
       case KeyEvent.VK_UP:
          puyoLogic.rotateCW();
          break;   
        case KeyEvent.VK_DOWN:
          puyoLogic.rotateCCW();
          break;    
        case KeyEvent.VK_LEFT:
          puyoLogic.moveLeft();
          break;
        case KeyEvent.VK_RIGHT:
          puyoLogic.moveRight();
          break;

        case KeyEvent.VK_PAGE_UP:
          puyoLogic.speedUp();
          break;
        case KeyEvent.VK_PAGE_DOWN:
          puyoLogic.speedDown();
          break;
          
        case KeyEvent.VK_SPACE:
        case KeyEvent.VK_P:
          puyoLogic.changePauseState();
          break;
        default:
      }

    if (keyCode == KeyEvent.VK_S ||
        keyCode == KeyEvent.VK_ENTER){
      puyoLogic.running = true;
      beginPuyo();
    }
  }

  public void keyReleased(KeyEvent e){
  }

  public void keyTyped(KeyEvent e){
  }

  /**draw puyo images according to the stored game data*/
  public void repaint(){
    Graphics g=paintCanvas.getGraphics();
    if (doubleBuffer != null) {
        // paint to double buffer
        Graphics g2 = doubleBuffer.getGraphics();
        g2.setColor(Color.WHITE);
        g2.fillRect(0,0,canvasWidth,canvasHeight);    
        // draw the balls
        drawBalls(g2);
        g2.dispose();
        // copy double buffer to screen
        g.drawImage(doubleBuffer, 0, 0, null);
    }else{
        doubleBuffer = paintCanvas.createImage(canvasWidth, canvasHeight);        
    }
    updateScore();
   // System.out.println("in repaint"+(doubleBuffer==null));
  }
  
  private int color2ImageIndex(int color){
      return color-1;
  }
  
  private void drawBalls(Graphics g){
      if(puyoLogic != null ){
        for(int i=0;i<puyoLogic.numDroppingBalls;i++){         
            g.drawImage(puyoImages[color2ImageIndex(puyoLogic.droppingBalls[i].color)],
                        (puyoLogic.droppingBalls[i].x-1)*ballWidth,                        
                        (boardHeight-puyoLogic.droppingBalls[i].y)*ballHeight,
                        null);
        }
        for(int i=1;i<boardWidth+1;i++)
            for(int j=1;j<boardHeight+1;j++)
                if(puyoLogic.accumBalls[i][j] != puyoLogic.puyoEmpty){
                    g.drawImage(puyoImages[color2ImageIndex(puyoLogic.accumBalls[i][j])],
                        (i-1)*ballWidth,
                        (boardHeight-j)*ballHeight,
                        null);
                }
      }
  }

  private void updateScore(){
    if(puyoLogic != null){
      String s = "Score: " + puyoLogic.score;
      labelScore.setText(s);
    }
  }

  private void beginPuyo(){
    if (puyoLogic == null || !puyoLogic.isRunning()){
      puyoLogic = new PuyoLogic(boardWidth, boardHeight);
      (new Thread(this)).start();
    }
  }

   /**Main game logic*/
    public void run() {    
       while(true){
         try{
            Thread.sleep(puyoLogic.getTimeDelay());
         }
         catch(Exception e){
           break;
         }
         if(puyoLogic.isRunning() && !puyoLogic.isPaused() && puyoLogic.drop()){   
             repaint();
             try{
                Thread.sleep(puyoLogic.getTimeDelay());
             }
             catch(Exception e){
                break;
             }
             while(puyoLogic.checkAccumBalls()){ 
                 try{                    
                    Thread.sleep(2*puyoLogic.getTimeDelay());
                 }
                 catch(Exception e){
                    break;
                 }                  
                 repaint(); 
                 while(puyoLogic.freeFalling());  
                 try{
                     Thread.sleep(puyoLogic.getTimeDelay());
                 } catch(Exception e){
                     break;
                 }
                 repaint();
             }             
             if(!puyoLogic.initDroppingBalls()) {                   
                if(JOptionPane.showConfirmDialog(
                     null,"You lost the game. Restart one?","Game Over",
                     JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION){ 
                       puyoLogic.initAll(); 
                   }else {
                       //running=false; //optionally, you might not want to exit the program?
                       System.exit(0);
                   }
               }           
         }
         repaint();         
       }       
   }
    
  public static void main(String[] args){
    PuyoWindow puyoWin = new PuyoWindow();
  }
  

}
